Матч
255, К-ый элемент (KthElement)
Дивизион 2, Уровень
3
Обозначим через F(n) функцию, которая вычисляет количество
единиц в бинарном представлении числа n.
Например, F(279) = 5, так как 279 = (100010111)2. Последовательность
Х строится следующим образом: X0 = 0, Xi = A * F(Xi-1)
+ B. По заданным A, B, K найти K – ый элемент последовательности Х.
Класс: KthElement
Метод: int
find(int A, int B, int K)
Ограничения:
0 £ A, B £ 106, 1 £ K £ 109.
Вход. Три числа A, B, K.
Выход. Значение Xk.
Пример входа
A |
B |
K |
0 |
12 |
5 |
1 |
7 |
15 |
15 |
21 |
500000001 |
Пример выхода
12
9
51
РЕШЕНИЕ
математика
F(Xi) принимают конечное множество значений. Поэтому
начиная с некоторого индекса pos,
значения F(Xi) начнут
образовывать повторяющийся цикл. Предположим, что индекс len минимальный, для которого Xpos
= Xlen. Таким образом,
длина цикла (повторяющейся части) равна len
– pos. Все значения F(Xi), где i < len, будем хранить
в векторе seq. То есть seq[i] = F(Xi) для i < len. Если искомый
номер последовательности k < len, то достаточно вывести значение seq[k]. Иначе ищем минимальный индекс j последовательности X, для которого Xj = Xk. Он равен j
= pos + (k – pos) % (len – pos). Выводим seq[j] = Xj.
ПРИМЕР
Рассмотрим третий тест.
Последовательность Xi
имеет вид: 0, 21, 66, 51, 81, 66, 51, 81, 66, ... . Циклическая часть
последовательности состоит из трех чисел и имеет вид 66, 51, 81. Для этой
последовательности pos = 2 (нумерация
индексов последовательности и вектора начинается с нуля), len = 5 (X2 = X5). Вычисляем минимальный
индекс j последовательности X, для
которого Xj = Xk: j = pos + (k – pos)
% (len – pos) = 2 + (500000001 – 2) % (5 – 2) = 2 + 1 = 3. Таким образом X500000001
= X3 = 51.
Функция int f(int x) вычисляет F(x).
ПРОГРАММА
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
class KthElement
{
public:
int f(int x)
{
int res = 0;
while(x > 0)
{
x = x & (x - 1);
res++;
}
return res;
}
int find(int a, int b, int k)
{
vector<int> seq;
int x = 0, pos, len;
while(std::find(seq.begin(),seq.end(),x)
== seq.end())
{
seq.push_back(x);
x = a * f(x) + b;
}
pos = (int)(std::find(seq.begin(),seq.end(),x)
- seq.begin());
len = seq.size();
if
(k < len) return seq[k];
return seq[pos + (k - pos) % (len -
pos)];
}
};